package pl.s7n.paint.edits;

import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;

import javax.swing.undo.AbstractUndoableEdit;
import javax.swing.undo.UndoableEditSupport;

import pl.s7n.paint.DrawableCanvas;
import pl.s7n.paint.commands.AbstractStrokeCmd;
import pl.s7n.paint.commands.ResizeCmd;
import pl.s7n.paint.utils.Pair;
import pl.s7n.paint.utils.Utils;

public class ResizeEditManager extends AbstractEditManager<ResizeCmd> {

  private DrawableCanvas                                     parent;
  private BufferedImage                                      currentBackgroundImage;

  private List<Pair<BufferedImage, List<AbstractStrokeCmd>>> resizes = new ArrayList<Pair<BufferedImage, List<AbstractStrokeCmd>>>();

  public ResizeEditManager(UndoableEditSupport undoableEditSupport, DrawableCanvas parent) {
    super(undoableEditSupport);
    this.parent = parent;
  }
  
  public boolean draw(Graphics2D g) {
    if (currentBackgroundImage != null) {
      g.drawRenderedImage(currentBackgroundImage, new AffineTransform());
      return true;
    }
    return false;
  }

  public void editPerformed(ResizeCmd action) {
    undoableEditSupport.postEdit(new ResizeEdit(action));

    doRedo(action);
  }

  private void doRedo(ResizeCmd action) {
    BufferedImage oldImage = action.getOldImage();
    List<AbstractStrokeCmd> drawingEdits = new ArrayList<AbstractStrokeCmd>(parent.getDrawingEditManager().actions);
    resizes.add(new Pair<BufferedImage, List<AbstractStrokeCmd>>(oldImage, drawingEdits));
    parent.getDrawingEditManager().reset();

    parent.setImage(action.getNewImage(), false);
    currentBackgroundImage = Utils.copyImage(action.getNewImage());

    parent.redraw();
  }

  private void doUndo() {
    if (resizes.isEmpty()) {
      currentBackgroundImage = null;
    } else {
      Pair<BufferedImage, List<AbstractStrokeCmd>> cur = resizes.remove(resizes.size() - 1);
      parent.setImage(cur.getFirst(), false);
      parent.getDrawingEditManager().actions.addAll(cur.getSecond());

      if (resizes.isEmpty()) {
        currentBackgroundImage = null;
      } else {
        currentBackgroundImage = resizes.get(resizes.size() - 1).getFirst();
      }
    }
    parent.redraw();
  }
  
  @Override
  public void reset() {
    resizes.clear();
    currentBackgroundImage = null;
  }
  
  @Override
  public boolean hasActions() {
    return !resizes.isEmpty();
  }

  private class ResizeEdit extends AbstractUndoableEdit {
    private static final long serialVersionUID = 335755372811578290L;

    ResizeCmd                 newAction;

    public ResizeEdit(ResizeCmd newAction) {
      this.newAction = newAction;
    }

    @Override
    public String getRedoPresentationName() {
      return "Redo " + newAction.toString();
    }

    @Override
    public String getUndoPresentationName() {
      return "Undo " + newAction.toString();
    }

    @Override
    public void undo() {
      super.undo();
      doUndo();
    }

    @Override
    public void redo() {
      super.redo();
      doRedo(newAction);
    }
  }
}
